package com.chendx.store.seckill.thread;

import com.alibaba.fastjson.JSON;
import com.chendx.model.seckill.pojo.SeckillGoods;
import com.chendx.model.seckill.pojo.SeckillOrder;
import com.chendx.model.seckill.vo.SeckillStatus;
import com.chendx.store.common.constants.ampq.AMQPConstants;
import com.chendx.store.common.constants.seckill.SeckillConstants;
import com.chendx.store.common.entity.IdWorker;
import com.chendx.store.seckill.mapper.SeckillGoodsMapper;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.Random;

/**
 * Created by chendx on 2022/4/22.
 */
@Component
public class MultiThreadingCreateOrder {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private Environment env;
    @Async
    public void createOrder() {
        try {
            Random random = new Random();
            int count = random.nextInt(10) + 5;
            System.out.println("准备执行....");
            Thread.sleep(count * 1000);
            System.out.println("开始执行....");
            String pop = redisTemplate.boundListOps(SeckillConstants.SECKILL_ORDER_QUEUE).rightPop();
            SeckillStatus seckillStatus = JSON.parseObject(pop, SeckillStatus.class);
            if (seckillStatus != null){
                Object obj = redisTemplate.boundHashOps(SeckillConstants.USER_QUEUE_STATUS).get(seckillStatus.getUsername());
                if (obj == null){
                    return;
                }
                String username = seckillStatus.getUsername();
                String id = String.valueOf(seckillStatus.getGoodsId()); //抢购商品id
                String time = seckillStatus.getTime();//时间区间
                //库存list -1
                String sgoods = redisTemplate.boundListOps(SeckillConstants.SECKILL_GOODS_COUNT_LIST + id).rightPop();
                if (StringUtils.isEmpty(sgoods)){
                    System.out.println("已售罄");
                    clearQueue(username);
                    return ;
                }
                //获取抢购商品信息
                Object o = redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_LIST + time).get(id);
                if (StringUtils.isEmpty(o)){
                    return;
                }
                SeckillGoods seckillGoods = JSON.parseObject(o.toString(), SeckillGoods.class);
                //封装抢购订单
                Long orderId = idWorker.nextId();
                SeckillOrder order = new SeckillOrder();
                order.setId(orderId); //id
                order.setSeckillId(Long.valueOf(id));//商品id
                order.setUserId(username);//用户名
                order.setCreateTime(new Date());//创建时间
                order.setMoney(seckillGoods.getCostPrice());//订单金额
                order.setStatus("0");//订单状态 0未支付
                order.setPayStatus("0");//订单状态 0未支付
                order.setReceiver(seckillStatus.getReceiver());//收件人
                order.setReceiverAddress(seckillStatus.getReceiverAddress());//收件地址
                order.setReceiverMobile(seckillStatus.getReceiverMoblie());//联系方式
                order.setPostFee(0);
                order.setOrderStatus("0");
                order.setConsignStatus("0");
                //订单存到redis中
                redisTemplate.boundHashOps(SeckillConstants.SECKILL_ORDER).put(username,JSON.toJSONString(order));

                System.out.println("goods "+ id);
                Integer stockCount = Math.toIntExact(redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_COUNT).increment(id, -1));
                //修改抢单排队状态
                seckillStatus.setStatus("2");
                seckillStatus.setMoney(Float.valueOf(order.getMoney()));
                seckillStatus.setOrderId(orderId);
                redisTemplate.boundHashOps(SeckillConstants.USER_QUEUE_STATUS).put(username,JSON.toJSONString(seckillStatus));
                //判断库存剩余数量
                if (stockCount <= 0){
                    seckillGoods.setStockCount(0);
                    seckillGoodsMapper.updateById(seckillGoods);
                    redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_LIST + time).put(id,JSON.toJSONString(seckillGoods));
                    redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_COUNT).delete(id);
                }else {
                    seckillGoods.setStockCount(stockCount);
                    redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_LIST + time).put(id,JSON.toJSONString(seckillGoods));
                }

                rabbitTemplate.convertAndSend(env.getProperty(AMQPConstants.MQ_SECKILL_QUEUE_SECKILLORDERDELAYTIMER),
                        (Object) JSON.toJSONString(seckillStatus), new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        message.getMessageProperties().setExpiration("30000");
                        return message;
                    }
                });
            }
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    /**
     * 清理用户排队信息
     * @param username
     */
    private void clearQueue(String username) {
        redisTemplate.boundHashOps(SeckillConstants.USER_QUEUE_STATUS).delete(username);
        redisTemplate.boundHashOps(SeckillConstants.USER_QUEUE_COUNT).delete(username);
    }
}
